#!/usr/bin/python
# -*- coding: utf-8 -*-

import time

import dsu_comm

BM3823_OSC_FREQ      = 25000000
BM3823_PLL_MIN       = 0b011
BM3823_PLL_DIN       = 0b010
BM3823_PLL_DDR_DIN   = 0b101

BM3823_MAIN_PLL_FREQ = BM3823_OSC_FREQ * BM3823_PLL_MIN * 16
BM3823_SYSTEM_FREQ   = BM3823_MAIN_PLL_FREQ / (2 * BM3823_PLL_DIN)
BM3823_DDR_FREQ      = BM3823_MAIN_PLL_FREQ / BM3823_PLL_DDR_DIN
BM3823_MAC_FREQ      = BM3823_OSC_FREQ * 20
BM3823_UART_FREQ     = BM3823_SYSTEM_FREQ / 3

BM3823_SYSTEM_FREQ_M = BM3823_SYSTEM_FREQ / 1e6

comm = dsu_comm.DSU_Comm()

load_addr_glo = 0xFFFFFFFF
gsmon_cmd_dict = {}

def gsmon_con_helper(user_list):
	args_lim  = 3
	res       = False

	while(True):
		if((len(user_list) != 2) and (len(user_list) != 3)):
			print("ARGS INVALID!")
			break

		try:
			port = user_list[1]

			if(len(user_list) == 2):
				baud = 38400
			else:
				baud = int(user_list[2], 10)

			if(comm.serialPort_init == True):
				comm.close_serial_port()

			if comm.connect(port_name=port, baudrate=baud):
				if comm.bm3823_dsu_connect():
					model = comm.bm3823_chip_id_get()
					print("芯片型号: %s" % (model))

					freq, scaler_get  = comm.bm3823_freq_get()
					print("芯片主频设置值:%.3f MHz, 计算值:%.3f MHz" % (BM3823_SYSTEM_FREQ_M, freq))

					scaler = comm.bm3823_dsu_scaler_calc(freq*1e6, baud)

					if(scaler != scaler_get):
						comm.bm3823_dsu_scaler_set(BM3823_SYSTEM_FREQ, baud)

					comm.bm3823_dsu_init_seq()
					comm.bm3823_ddr_init_seq()

					res = True
		except Exception as e:
			print(e)
			break

		break

	return res

def gsmon_setbaud_helper(user_list):
	args_lim  = 2
	res       = False
	arg_accept = [9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 500000, 1000000]

	while(True):
		if(len(user_list) != args_lim):
			print("ARGS INVALID!")
			break
		if(comm.dsu_comm_init == False):
			break

		try:
			new_baud  = int(user_list[1], 10)
			if(new_baud not in arg_accept):
				break

			comm.bm3823_dsu_scaler_set(BM3823_SYSTEM_FREQ, new_baud)
			time.sleep(0.005)

			model = comm.bm3823_chip_id_get()
			print("芯片型号: %s" % (model))

			freq, scaler_get  = comm.bm3823_freq_get()
			print("芯片主频设置值:%.3f MHz, 计算值:%.3f MHz" % (BM3823_SYSTEM_FREQ_M, freq))

		except Exception as e:
			print(e)
			break
		res = True
		break

	return res

def gsmon_loadbin_helper(user_list):
	args_lim  = 3
	res       = False
	global load_addr_glo

	while(True):
		if(len(user_list) != args_lim):
			print("ARGS INVALID!")
			break
		if(comm.dsu_comm_init == False):
			break
		if(comm.prog_running == True):
			print("Target is running!")
			break

		try:
			load_addr = int(user_list[1], 16)
			file_name = user_list[2]

			bin_file = open(file_name, "rb")
			bin_file_cont = bin_file.read()
			bin_file.close()

			comm.bm3823_bin_loader(load_addr, bin_file_cont, speed_flag=True)

			load_addr_glo = load_addr
		except Exception as e:
			print(e)
			break

		res = True
		break

	return res

def gsmon_loadelf_helper(user_list):
	args_lim  = 2
	res       = False
	global load_addr_glo

	while(True):
		if(len(user_list) != args_lim):
			print("ARGS INVALID!")
			break
		if(comm.dsu_comm_init == False):
			break
		if(comm.prog_running == True):
			print("Target is running!")
			break

		try:
			file_name = user_list[1]
			load_addr = comm.bm3823_elf_loader(file_name, speed_flag=True)

			load_addr_glo = load_addr
		except Exception as e:
			print(e)
			break

		res = True
		break

	return res

def gsmon_rmem_helper(user_list):
	args_lim  = 3
	res       = False

	while(True):
		if(len(user_list) != args_lim):
			print("ARGS INVALID!")
			break
		if(comm.dsu_comm_init == False):
			break

		try:
			mem_addr = int(user_list[1], 16)
			mem_len  = int(user_list[2])

			mem_list = comm.dsu_reg_read(mem_addr, mem_len)

			mem_str  = ""
#			mem_str += ("READ %4d DWORD(S) from 0x%08X\n" % (mem_len, mem_addr))
			for _ in range(len(mem_list)):
				if((_ % 4) == 0):
					mem_str += ("\n0x%08X\t" % (mem_addr + (_ << 2)))
				mem_str += ("%08X " % (mem_list[_]))

			print(mem_str)

		except Exception as e:
			print(e)
			break

		res = True
		break

	return res

def gsmon_wmem_helper(user_list):
	args_lim  = 3
	res       = False

	while(True):
		if(len(user_list) < args_lim):
			print("ARGS INVALID!")
			break
		if(comm.dsu_comm_init == False):
			break

		try:
			mem_addr = int(user_list[1], 16)
			mem_data = []

			for _ in user_list[2:]:
				mem_data.append(int(_, 16))

			comm.dsu_reg_write(mem_addr, mem_data)
		except Exception as e:
			print(e)
			break

		res = True
		break

	return res

def gsmon_go_helper(user_list):
	args_lim  = 2
	res       = False
	global load_addr_glo

	while(True):
		if(len(user_list) != args_lim):
			print("ARGS INVALID!")
			break
		if(comm.dsu_comm_init == False):
			break
		if(comm.prog_running == True):
			print("Target is running!")
			break

		try:
			go_addr = int(user_list[1], 16)
			comm.bm3823_go_nobreak(go_addr, wait_flag=False)
		except Exception as e:
			print(e)
			break

		res = True
		break

	return res

def gsmon_run_helper(user_list):
	args_lim  = 1
	res       = False

	while(True):
		if(len(user_list) != args_lim):
			print("ARGS INVALID!")
			break
		if(comm.dsu_comm_init == False):
			break
		if(comm.prog_running == True):
			print("Target is running!")
			break

		try:
			if(load_addr_glo == 0xFFFFFFFF):
				print("ARGS INVALID!")
				break
			comm.bm3823_go_nobreak(load_addr_glo, wait_flag=False)
		except Exception as e:
			print(e)
			break

		res = True
		break

	return res

def gsmon_halt_helper(user_list):
	res       = False

	while(True):
		if(comm.dsu_comm_init == False):
			break

		try:
			comm.bm3823_dsu_set_debug_mode()
		except Exception as e:
			print(e)
			break

		res = True
		break

	return res

def gsmon_ddrinit_helper(user_list):
	res       = False

	while(True):
		if(comm.dsu_comm_init == False):
			break

		try:
			comm.bm3823_ddr_init_seq()
		except Exception as e:
			print(e)
			break

		res = True
		break

	return res

def gsmon_helper(user_list):
	res       = False

	while(True):
		for key, value in gsmon_cmd_dict.items():
			help_cont = key + "\t" + value[2] + "\n"
			print(help_cont)
		break

	return res

gsmon_cmd_dict = {  "con":(gsmon_con_helper, 2, "连接 DSU，默认波特率38400\n\t\tcon [COM口] [波特率(可选)]\n\t例:\tcon COM4\n\t\tcon COM4 460800"), \
					"setbaud":(gsmon_setbaud_helper, 2, "设置 DSU 波特率，可提高速度，最大波特率921600\n\t\tsetbaud [波特率]\n\t例:\tsetbaud 460800"), \
					"loadbin":(gsmon_loadbin_helper, 3, "加载 bin 文件到指定内存区域\n\t\tloadbin [加载地址] [bin文件路径]\n\t例:\tloadbin 0xA0000000 ../demo/uart_test/bin_ocram/uart_test.bin"), \
					"loadelf":(gsmon_loadelf_helper, 2, "加载 elf 文件\n\t\tloadelf [elf文件路径]\n\t例:\tloadelf ../demo/uart_test/bin_ddr/uart_test.elf"), \
					"rmem":(gsmon_rmem_helper, 2, "从指定地址读取数据\n\t\trmem [地址]\n\t例:\trmem 0xA0000000 32"), \
					"wmem":(gsmon_wmem_helper, 3, "向指定地址写入数据\n\t\twmem [地址] [n*数据]\n\t例:\twmem 0x90000000 0x000075FA 0x031FF1FF 0x00000000 0x00000000"), \
					"go":(gsmon_go_helper, 2, "从指定地址开始运行\n\t\tgo [地址]\n\t例:\tgo 0xA0000000\t"), \
					"run":(gsmon_run_helper, 1, "从加载地址开始运行"), \
					"halt":(gsmon_halt_helper, 1, "停止处理器自主运行"), \
					"ddrinit": (gsmon_ddrinit_helper, 1, "初始化DDR寄存器"), \
					"help":(gsmon_helper, 1, "打印指令帮助")}

if __name__ == "__main__":
	while(True):
		user_input = input("GSMON > ")
		user_list  = user_input.strip().split(" ")
		user_cmd   = user_list[0]

		if(user_cmd != ""):
			if((user_cmd in gsmon_cmd_dict) and (len(user_list) >= gsmon_cmd_dict[user_cmd][1])):
				gsmon_cmd_dict[user_cmd][0](user_list)
			else:
				gsmon_helper([])

		if((comm.dsu_comm_init == True) and (comm.prog_running == True)):
			comm.bm3823_running_check()

#		time.sleep(0.001)